import Config from "./Config";
import LineLogic from "./LineLogic";
import Model from "./Model";
import MetaballMgr from "./MetaballMgr";
import Ball from "./Ball";
import TipLine from "./TipLine";

const { ccclass, property } = cc._decorator;

@ccclass
export default class GameDraw extends cc.Component {

    @property(cc.Prefab)
    Ball: cc.Prefab = null;

    @property(cc.Prefab)
    TopUI: cc.Prefab = null;

    @property(cc.Prefab)
    BottomUI: cc.Prefab = null;

    @property(cc.Prefab)
    Cup: cc.Prefab = null;

    @property(cc.Prefab)
    Line: cc.Prefab = null;

    @property(cc.Node)
    metaBall: cc.Node = null;

    lock: boolean = false;

    @property(cc.Node)
    waterPipe: cc.Node = null;

    @property(cc.Node)
    progressNode: cc.Node = null;

    @property(cc.Node)
    waterContainer: cc.Node = null;

    @property(cc.Prefab)
    SmokeEff: cc.Prefab = null;

    @property({type:cc.AudioClip})
    winClip: cc.AudioClip = null;

    @property({type:cc.AudioClip})
    waterClip: cc.AudioClip = null;

    currentLine: cc.Node

    cup: cc.Node

    @property([cc.Prefab])
    allObjs: cc.Prefab[] = []

    totalInk = 40;
    totalWater = 50
    waterCount = 0

    waters: any = []

    faceChange: boolean = false;

    linePosY: number = 0;
    //记录动态的物体，画线后才变动态，之前为静态
    dynamicObjs = []
    redObjs = []

    //在水杯中的水滴数量

    cupInWaterObj: any = {};
    cupWater: number = 0;

    @property(cc.Node)
    tip: cc.Node = null;

    colliderPoints: cc.Vec2[];
    //已经绘制的长度，由于可以绘制多条
    hasDrawLen: number = 0


    onLoad() {
        Config.init()
        Model.game.selectedModel = 4

        //开启物理效果
        cc.director.getPhysicsManager().enabled = true
        cc.director.getPhysicsManager().gravity = new cc.Vec2(0, -1200);
        cc.director.getActionManager()['enabledAccumulator'] = true;
        cc.director.getActionManager()['FIXED_TIME_STEP'] = 1 / 30;
        cc.director.getPhysicsManager()['VELOCITY_ITERATIONS'] = 8;
        // cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_jointBit | cc.PhysicsManager.DrawBits.e_shapeBit;

        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);

        var size = cc.view.getVisibleSize();
        if (size.height / size.width > 2) {
            this.progressNode.getComponent(cc.Widget).top = 200
        } else {
            this.progressNode.getComponent(cc.Widget).top = 145
        }
        this.createWorld()

        var top = cc.instantiate(this.TopUI)
        this.node.addChild(top)

        this.metaBall.getComponent(MetaballMgr).waters = this.waters;

        var bottom = cc.instantiate(this.BottomUI)
        this.node.addChild(bottom);
        bottom.on('showTip', this.showTip, this);

        //开启抗锯齿
        // cc.macro.ENABLE_WEBGL_ANTIALIAS=true;

        this.progressNode.zIndex = 100
        this.tip.zIndex = 100
        this.node.getChildByName('gameTip').active = Model.game.selectedLevel == 1
    }
    createWorld() {

        //createCup
        var level = Model.game.selectedLevel;
        var data = Config.drawLevels[level];
        var cupPos = data[0]

        var cup = cc.instantiate(this.Cup);
        cup.getComponent(cc.RigidBody).type = cc.RigidBodyType.Static;
        cup.x = cupPos[0]
        cup.y = cupPos[1]
        this.waterContainer.addChild(cup)
        this.cup = cup;
        if (cupPos.length > 2) {
            cup.angle = -cupPos[2]
        }

        var cupData = Config.cupDatas[1]
        // for (var i = 0; i < cupData.polygonColliderList.length; i++) {
        //     var collider = cup.addComponent(cc.PhysicsPolygonCollider)
        //     collider.points = cupData.polygonColliderList[i]
        //     collider.density = 10
        //     collider.apply()
        // }
        cup.getComponent(cc.RigidBody).enabledContactListener = true
        cup.getComponent(cc.RigidBody).onBeginContact = (contact, selfCollider, otherCollider) => {
            this.onBeginContact(contact, selfCollider, otherCollider)
        }
        this.linePosY = cupData.linePosY + cup.y;
        //添加一个传感器用于检测水杯中的水滴
        var collider = this.cup.addComponent(cc.PhysicsPolygonCollider);
        this.colliderPoints = [cc.v2(-43, -82), cc.v2(43, -82), cc.v2(72, 70), cc.v2(-69, 70)]
        collider.points = this.colliderPoints
        collider.sensor = true
        collider.apply()


        //水龙头
        var pipeInfo = data[1]
        this.waterPipe.x = pipeInfo[0]
        this.waterPipe.y = pipeInfo[1]
        this.waterPipe.angle = -pipeInfo[2]

        this.totalInk = data[3]
        this.totalWater = data[4]

        //平台
        for (var i = 5; i < data.length; i++) {
            var brickType = data[i][0]
            var brick = cc.instantiate(this.allObjs[brickType - 1])
            brick.x = data[i][1]
            brick.y = data[i][2]

            if (brickType == 3 || brickType == 8 || brickType == 11 || brickType == 13)//矩形
            {
                brick.setContentSize(cc.size(data[i][3], data[i][4]))
                brick.getComponent(cc.PhysicsBoxCollider).size = cc.size(cc.size(data[i][3], data[i][4]))
                brick.getComponent(cc.PhysicsBoxCollider).apply()

                //火焰特殊处理
                if (brickType == 11) {
                    brick.getComponent(cc.RigidBody).onBeginContact = (contact, selfCollider, otherCollider) => {
                        this.onBeginContact(contact, selfCollider, otherCollider)
                    }
                }
                if (brickType == 13) {
                    var size = brick.getComponent(cc.PhysicsBoxCollider).size
                    var points = [cc.v2(brick.x - size.width * 0.5, brick.y - size.height * 0.5),
                    cc.v2(brick.x + size.width * 0.5, brick.y - size.height * 0.5),
                    cc.v2(brick.x + size.width * 0.5, brick.y + size.height * 0.5),
                    cc.v2(brick.x - size.width * 0.5, brick.y + size.height * 0.5)]
                    this.redObjs.push(points)
                }

            } else if (brickType == 7 || brickType == 4)//圆
            {
                brick.setContentSize(cc.size(data[i][3], data[i][4]))
                brick.getComponent(cc.PhysicsCircleCollider).radius = data[i][3] * 0.5
                brick.getComponent(cc.PhysicsCircleCollider).apply()
            }
            brick.angle = -data[i][5]
            if (brickType == 13)
                this.waterContainer.addChild(brick, -1)
            else
                this.waterContainer.addChild(brick)

            if (brick.getComponent(cc.RigidBody) != null) {
                if (brick.getComponent(cc.RigidBody).type == cc.RigidBodyType.Dynamic) {
                    this.dynamicObjs.push(brick);
                }
                brick.getComponent(cc.RigidBody).type = cc.RigidBodyType.Static
            }
            if (Model.game.selectedLevel == 32 && brickType == 6)//特殊处理下这个球
            {
                brick.getComponent(cc.PhysicsCircleCollider).density = 0.01
                brick.getComponent(cc.PhysicsCircleCollider).apply()
            }
        }

    }

    start() {
        //提示
        var level = Model.game.selectedLevel;
        var data = Config.drawLevels[level];
        this.tip.getComponent(TipLine).points = data[2]
        this.tip.active = false;
    }
    checkInRed(pos: cc.Vec2) {
        var size = cc.view.getVisibleSize();
        for (var temp of this.redObjs) {

            if (cc.Intersection.pointInPolygon(cc.v2(pos.x - size.width * 0.5, pos.y - size.height * 0.5), temp)) {
                console.log('lllllllllllllllllllll')
                return true
            }
        }

        return false;
    }
    canMove: boolean = true;
    onTouchStart(e) {
        if (this.lock) return;
        var pos = e.getLocation();
        if (this.checkInRed(pos)) {
            this.canMove = false;
            return
        } else {
            this.canMove = true;
        }

        if (this.currentLine != null) {
            this.hasDrawLen += this.currentLine.getComponent(LineLogic).points.length
        }
        var line = cc.instantiate(this.Line);
        this.node.addChild(line);
        this.currentLine = line

        this.currentLine.getComponent(LineLogic).onTouchStart(e)
        return true
    }
    onTouchMove(e) {
        if (!this.canMove)
            return

        var totalLen = this.currentLine.getComponent(LineLogic).points.length + this.hasDrawLen;
        if (totalLen <= this.totalInk) {
            this.currentLine.getComponent(LineLogic).onTouchMove(e)

            var p = (this.totalInk - totalLen) / this.totalInk;
            this.progressNode.getComponent(cc.ProgressBar).progress = p;
            this.progressNode.getChildByName('progress_label').getComponent(cc.Label).string = Math.floor(p * 100) + '%'

            if (p < 0.8) {
                this.progressNode.getChildByName('star3').active = false;
                this.progressNode.getChildByName('stargray3').active = true;
            }
            if (p < 0.6) {
                this.progressNode.getChildByName('star2').active = false;
                this.progressNode.getChildByName('stargray2').active = true;
            }
            if (p < 0.1) {
                this.progressNode.getChildByName('star1').active = false;
                this.progressNode.getChildByName('stargray1').active = true;
            }

        }

    }
    onTouchEnd(e) {
        if (!this.canMove)
            return
        this.currentLine.getComponent(LineLogic).onTouchEnd(e)
        this.cup.getComponent(cc.RigidBody).type = cc.RigidBodyType.Dynamic;
        for (var obj of this.dynamicObjs) {
            obj.getComponent(cc.RigidBody).type = cc.RigidBodyType.Dynamic;
        }

        this.startDropWater()
    }

    //开始滴水
    startDropWater() {
        console.log('开始创建水')
        this.schedule(this.createWater, 0.06)
    }
    waterSoundDelay = 0.2;
    waterSoundDelayCount = 10;
    createWater() {
        if (this.waterCount < this.totalWater) {
            this.waterCount++
            var ball = cc.instantiate(this.Ball);
            this.waterSoundDelayCount += 0.06
            if (this.waterSoundDelayCount > this.waterSoundDelay) {
                this.waterSoundDelayCount = 0
                cc.audioEngine.playEffect(this.waterClip, false)
            }


            // console.log(this.waterPipe.rotation)
            if (this.waterPipe.angle == 0) {
                ball.x = this.waterPipe.x + Math.random() * 8 - 16
                ball.y = this.waterPipe.y + Math.random() * 5 - 75
                ball.getComponent(cc.RigidBody).linearVelocity = cc.v2(0, -0)
            } else if (this.waterPipe.angle >= 181 && this.waterPipe.angle <= 178) {
                ball.x = this.waterPipe.x + Math.random() * 8 - 16
                ball.y = this.waterPipe.y + Math.random() * 5 + 75
                ball.getComponent(cc.RigidBody).linearVelocity = cc.v2(0, 100)

            } else {

                var center = this.cup.getComponent(cc.RigidBody).getWorldCenter();
                var sign = this.waterPipe.angle < 0 ? -1 : 1
                ball.x = this.waterPipe.x + 60 * sign + Math.random() * 8 - 4
                ball.y = this.waterPipe.y + Math.random() * 10 - 5

                ball.getComponent(cc.RigidBody).linearVelocity = cc.v2(sign * 150, 0)
                // ball.getComponent(cc.RigidBody).applyLinearImpulse(cc.v2(200000,200000), cc.v2(center.x, center.y), true);
                // ball.getComponent(cc.RigidBody).applyForce(cc.v2(1000,0),center,true)
            }



            ball.getComponent(Ball).id = this.waterCount
            ball.getComponent(cc.PhysicsCircleCollider).density = 1
            ball.getComponent(cc.PhysicsCircleCollider).restitution = 0.2
            ball.getComponent(cc.PhysicsCircleCollider).apply()
            this.waterContainer.addChild(ball, -1)
            this.waters.push(ball);
        } else {
            this.unschedule(this.createWater)
            this.schedule(this.checkGame, 0.1)
        }

    }
    showFace(type: number) {
        this.cup.getChildByName('facenormal').active = false;
        this.cup.getChildByName('facewin').active = false;
        this.cup.getChildByName('facelose').active = false;
        if (type == 2) {
            this.cup.getChildByName('facewin').active = true;
        } else if (type == 1) {
            this.cup.getChildByName('facelose').active = true;
        } else if (type == 0) {
            this.cup.getChildByName('facenormal').active = true;
        }
    }

    update(dt) {

        if (this.waterCount > 0) {
            this.metaBall.getComponent(MetaballMgr).draw()

            for (var i = 0; i < this.waters.length; i++) {
                if (this.waters[i].y < -1000) {
                    this.waters.splice(i, 1)
                    i--
                }
            }
        }

    }
    checkGame() {
        if (this.lock) return

        //检测胜利
        if (this.waters.length >= 39) {
            var newRect = []
            for (var a of this.colliderPoints) {
                newRect.push(cc.v2(this.cup.x + a.x, a.y + this.cup.y))
            }
            var count = 0
            for (var temp of this.waters) {
                if (cc.Intersection.pointInPolygon(temp.position, newRect)) {
                    count++;
                }
            }
            //console.log(count);
            if (count >= 39) {
                this.gameWin();
            }
        }
        //失败检测
        this.checkLose();
    }
    checkLose() {
        if (this.waters.length <= 15) {
            this.gameLose()
            return;
        }

        var allSleep: boolean = true
        for (var ball of this.waters) {
            if (ball.getComponent(cc.RigidBody).awake) {
                allSleep = false
                break
            }
        }
        if (allSleep) {
            this.gameLose()
        }
    }
    gameWin() {
        if (this.lock) return
        this.unscheduleAllCallbacks()
        this.lock = true
        Model.game.win = true
        this.showFace(2)
        this.scheduleOnce(this.delayShowEnd, 1)
        cc.audioEngine.playEffect(this.winClip, false)
        this.saveData();
    }
    gameLose() {
        if (this.lock) return
        this.unscheduleAllCallbacks()
        this.lock = true
        Model.game.win = false
        this.showFace(1)
        this.scheduleOnce(this.delayShowEnd, 1)
    }
    delayShowEnd() {

        cc.director.loadScene('gameEnd')


    }
    showTip() {
        console.log('显示提示')
        this.tip.active = true
    }

    onBeginContact(contact, selfCollider, otherCollider) {


        // console.log(selfCollider.node.name, otherCollider.node.name)

        if ((selfCollider instanceof cc.PhysicsBoxCollider) && selfCollider.node.name == 'Cup3' && otherCollider.node.name == 'Ball') {

            //selfCollider.getAABB()
            // if (this.cupInWaterObj[otherCollider.node.getComponent(Ball).id] == null) {
            //     this.cupInWaterObj[otherCollider.node.getComponent(Ball).id] = true
            //     this.cupWater++
            //     // console.log(this.cupWater,'aaaaa')
            //     if (this.cupWater >= 30) {
            //         this.gameWin()
            //     }
            // }

            if (!this.faceChange) {
                this.faceChange = true
                this.showFace(1);
            }

        }
        //火焰
        if (selfCollider.node.name == 'r11' && otherCollider.node.name == 'Ball') {
            for (var i = 0; i < this.waters.length; i++) {
                if (this.waters[i] == otherCollider.node) {
                    this.waters.splice(i, 1)
                    i--
                    this.createSmokeEff(otherCollider.node.x, otherCollider.node.y)
                    otherCollider.node.destroy()
                    break;
                }
            }
        }
    }
    saveData() {
        var star = 0;

        if (this.progressNode.getChildByName('star1').active) star++
        if (this.progressNode.getChildByName('star2').active) star++
        if (this.progressNode.getChildByName('star3').active) star++
        Model.game.getStar = star;
        //存储
        if (Model.game.selectedLevel == Model.game.drawLevel) {
            Model.game.drawLevelInfo[Model.game.selectedLevel - 1] = star
            Model.game.drawLevelInfo[Model.game.selectedLevel] = -1

            Model.game.drawLevel = Model.game.selectedLevel + 1;
            Model.game.saveDraw()

        } else {
            if (star > Model.game.drawLevelInfo[Model.game.selectedLevel - 1]) {
                Model.game.drawLevelInfo[Model.game.selectedLevel - 1] = star
                Model.game.saveDraw();
            }
            //  Model.game.selectedLevel++
        }
    }
    createSmokeEff(x, y) {
        var eff = cc.instantiate(this.SmokeEff);
        eff.x = x;
        eff.y = y;
        this.node.addChild(eff);
    }

    checkFace() {

    }
}
